package com.yfore.jfinal.jsql.plugin.core;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

/**
 * 模板引擎
 * 核心使用underscore的模板引擎
 * @author farmer
 */
public class Template {
	/**
	 * 单例
	 */
	private static Template template = null;
	/**
	 * 
	 */
	private Context rhino = null;
	
	private Scriptable scope = null;
	
	/**
	 * 
	 */
	private Template(){
		rhino = Context.enter();
		scope = rhino.initStandardObjects();
		InputStreamReader reader = null;
		try {
			reader = new InputStreamReader(getClass().getResourceAsStream("Template.js"));
			rhino.evaluateReader(scope, reader, "Template", 0, null);
		} catch (IOException e) {
			throw new RuntimeException("模板JS初始化异常!", e);
		}
		finally{
			Context.exit();
			if(reader != null){
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 渲染模板
	 * @param template
	 * @param json
	 * @return
	 * @throws Exception 
	 */
	public SqlArgs render(String template ,String json) throws Exception{
		rhino = Context.enter();
		try {
			SqlArgs sqlArgs = new SqlArgs();
			List<Object> args = new ArrayList<Object>();
			ScriptableObject.putProperty(scope, "tpl", template);
			ScriptableObject.putProperty(scope, "json", json);
			sqlArgs.setSql((String) rhino.evaluateString(scope, "_.template(tpl)(eval('('+json+')'))",null,0,null));
			NativeArray array = (NativeArray) rhino.evaluateString(scope, "_.args", null, 0, null);
			for (Object object : array) {
				args.add(object);
			}
			sqlArgs.setArgs(args);
			return sqlArgs;
		} catch (Exception e) {
			throw new Exception("模板处理异常!", e);
		}
		finally{
			Context.exit();
		}
	}
	
	/**
	 * 获取模板引擎单例
	 * @return
	 */
	public static Template getTemplate() {
		if(template == null){
			template = new Template();
		}
		return template;
	}
	


}
